{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "IonDeviceTutorial.ipynb",
      "provenance": [],
      "collapsed_sections": [],
      "include_colab_link": true
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "view-in-github",
        "colab_type": "text"
      },
      "source": [
        "<a href=\"https://colab.research.google.com/github/JackHidary/quantumcomputingbook/blob/master/Notes/IonDeviceTutorial.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "bNlUyYQcgMF-",
        "colab_type": "text"
      },
      "source": [
        "# **Ion Device Class**\n",
        "This notebook provides an introductiong to making circuits that are compatable with  ion qubit devices in Cirq. IonDevice classes are available starting with release 0.5.0."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "IzkX8CaROO8s",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        ""
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "GTjMbjyAfJCK",
        "colab_type": "code",
        "outputId": "396de61f-b7a5-41de-c1fb-aad4f8144165",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 600
        }
      },
      "source": [
        "# install release containing NeutralAtomDevice and IonDevice classes\n",
        "!pip install cirq~=0.5.0"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Requirement already satisfied: cirq~=0.5.0 in /usr/local/lib/python3.6/dist-packages (0.5.0)\n",
            "Requirement already satisfied: google-api-python-client~=1.6 in /usr/local/lib/python3.6/dist-packages (from cirq~=0.5.0) (1.7.11)\n",
            "Requirement already satisfied: sortedcontainers~=2.0 in /usr/local/lib/python3.6/dist-packages (from cirq~=0.5.0) (2.1.0)\n",
            "Requirement already satisfied: scipy in /usr/local/lib/python3.6/dist-packages (from cirq~=0.5.0) (1.3.1)\n",
            "Requirement already satisfied: networkx~=2.1 in /usr/local/lib/python3.6/dist-packages (from cirq~=0.5.0) (2.4)\n",
            "Requirement already satisfied: protobuf~=3.5 in /usr/local/lib/python3.6/dist-packages (from cirq~=0.5.0) (3.10.0)\n",
            "Requirement already satisfied: sympy in /usr/local/lib/python3.6/dist-packages (from cirq~=0.5.0) (1.1.1)\n",
            "Requirement already satisfied: numpy~=1.12 in /usr/local/lib/python3.6/dist-packages (from cirq~=0.5.0) (1.17.3)\n",
            "Requirement already satisfied: requests~=2.18 in /usr/local/lib/python3.6/dist-packages (from cirq~=0.5.0) (2.21.0)\n",
            "Requirement already satisfied: typing-extensions in /usr/local/lib/python3.6/dist-packages (from cirq~=0.5.0) (3.6.6)\n",
            "Requirement already satisfied: matplotlib~=2.2 in /usr/local/lib/python3.6/dist-packages (from cirq~=0.5.0) (2.2.4)\n",
            "Requirement already satisfied: uritemplate<4dev,>=3.0.0 in /usr/local/lib/python3.6/dist-packages (from google-api-python-client~=1.6->cirq~=0.5.0) (3.0.0)\n",
            "Requirement already satisfied: google-auth-httplib2>=0.0.3 in /usr/local/lib/python3.6/dist-packages (from google-api-python-client~=1.6->cirq~=0.5.0) (0.0.3)\n",
            "Requirement already satisfied: httplib2<1dev,>=0.9.2 in /usr/local/lib/python3.6/dist-packages (from google-api-python-client~=1.6->cirq~=0.5.0) (0.11.3)\n",
            "Requirement already satisfied: six<2dev,>=1.6.1 in /usr/local/lib/python3.6/dist-packages (from google-api-python-client~=1.6->cirq~=0.5.0) (1.12.0)\n",
            "Requirement already satisfied: google-auth>=1.4.1 in /usr/local/lib/python3.6/dist-packages (from google-api-python-client~=1.6->cirq~=0.5.0) (1.4.2)\n",
            "Requirement already satisfied: decorator>=4.3.0 in /usr/local/lib/python3.6/dist-packages (from networkx~=2.1->cirq~=0.5.0) (4.4.1)\n",
            "Requirement already satisfied: setuptools in /usr/local/lib/python3.6/dist-packages (from protobuf~=3.5->cirq~=0.5.0) (41.4.0)\n",
            "Requirement already satisfied: mpmath>=0.19 in /usr/local/lib/python3.6/dist-packages (from sympy->cirq~=0.5.0) (1.1.0)\n",
            "Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.6/dist-packages (from requests~=2.18->cirq~=0.5.0) (2019.9.11)\n",
            "Requirement already satisfied: urllib3<1.25,>=1.21.1 in /usr/local/lib/python3.6/dist-packages (from requests~=2.18->cirq~=0.5.0) (1.24.3)\n",
            "Requirement already satisfied: chardet<3.1.0,>=3.0.2 in /usr/local/lib/python3.6/dist-packages (from requests~=2.18->cirq~=0.5.0) (3.0.4)\n",
            "Requirement already satisfied: idna<2.9,>=2.5 in /usr/local/lib/python3.6/dist-packages (from requests~=2.18->cirq~=0.5.0) (2.8)\n",
            "Requirement already satisfied: kiwisolver>=1.0.1 in /usr/local/lib/python3.6/dist-packages (from matplotlib~=2.2->cirq~=0.5.0) (1.1.0)\n",
            "Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.6/dist-packages (from matplotlib~=2.2->cirq~=0.5.0) (0.10.0)\n",
            "Requirement already satisfied: pytz in /usr/local/lib/python3.6/dist-packages (from matplotlib~=2.2->cirq~=0.5.0) (2018.9)\n",
            "Requirement already satisfied: python-dateutil>=2.1 in /usr/local/lib/python3.6/dist-packages (from matplotlib~=2.2->cirq~=0.5.0) (2.6.1)\n",
            "Requirement already satisfied: pyparsing!=2.0.4,!=2.1.2,!=2.1.6,>=2.0.1 in /usr/local/lib/python3.6/dist-packages (from matplotlib~=2.2->cirq~=0.5.0) (2.4.2)\n",
            "Requirement already satisfied: cachetools>=2.0.0 in /usr/local/lib/python3.6/dist-packages (from google-auth>=1.4.1->google-api-python-client~=1.6->cirq~=0.5.0) (3.1.1)\n",
            "Requirement already satisfied: pyasn1-modules>=0.2.1 in /usr/local/lib/python3.6/dist-packages (from google-auth>=1.4.1->google-api-python-client~=1.6->cirq~=0.5.0) (0.2.7)\n",
            "Requirement already satisfied: rsa>=3.1.4 in /usr/local/lib/python3.6/dist-packages (from google-auth>=1.4.1->google-api-python-client~=1.6->cirq~=0.5.0) (4.0)\n",
            "Requirement already satisfied: pyasn1<0.5.0,>=0.4.6 in /usr/local/lib/python3.6/dist-packages (from pyasn1-modules>=0.2.1->google-auth>=1.4.1->google-api-python-client~=1.6->cirq~=0.5.0) (0.4.7)\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "v3YMaPw1hfV_",
        "colab_type": "text"
      },
      "source": [
        "## IonDevice\n",
        "*Disclaimer: As with any proposed architecture for quantum computing, several research groups around the world are working towards a device based on ion qubits and each research group has a different approach. The IonDevice class will not accurately reflect all such devices. The class assumes a fully connected chain of ions with two-qubit gates implemented by an Ising type coupling known as the Molmer-Sorensen gate. The Molmer-Sorensen gate couples ions through the shared motional modes of the ion chain.  The ion motion and internal state decouples at the end of each gate. The class assumes this decoupling is perfect and does not explicitly model the ion motion.  This device is modeled on the ion trap quantum computer being constructed at Duke University as part of the National Science Foundation STAQ project and the participation in Cirq is part of the National Science Foundation EPiQC project's mission to provide open-source tools for mapping algorithms to hardware.*\n",
        "\n",
        "\n",
        "The IonDevice is described as a lineary array of qubits (LineQubit).  The user must specify the number of qubits in the line and the duration of gates and measurements.  The gate times and measurement times listed here are conservative values in microseconds."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "On6Wrh3XhSPO",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "import cirq\n",
        "import numpy as np\n",
        "import cirq.ion as ci\n",
        "from cirq import Simulator\n",
        "import itertools\n",
        "import random\n",
        "### number of qubits \n",
        "qubit_num = 5\n",
        "### define your qubits as line qubits for a linear ion trap\n",
        "qubit_list = cirq.LineQubit.range(qubit_num)\n",
        "### make your ion trap device with desired gate times and qubits\n",
        "us = 1000*cirq.Duration(nanos=1)\n",
        "ion_device = ci.IonDevice(measurement_duration=100*us,\n",
        "                        twoq_gates_duration=200*us,\n",
        "                        oneq_gates_duration=10*us,\n",
        "                        qubits=qubit_list)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ptv6T5WH8CLa",
        "colab_type": "text"
      },
      "source": [
        "---\n",
        "\n",
        "### Native Gate Set\n",
        "The gates supported by the IonDevice class are single qubit rotations about X, Y, and Z  and two qubit Molmer-Sorensen gates that are rotations about XX. \n",
        "\n",
        "\n",
        "\n",
        "---\n",
        "\n",
        "\n",
        "Some examples of gates in Cirq that the device supports are given below."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "Hotk4cHCpXCV",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "# Single Qubit Z rotation by Pi/5 radians\n",
        "ion_device.validate_gate(cirq.Rz(np.pi/5))\n",
        "# Single Qubit X rotation by Pi/7 radians \n",
        "ion_device.validate_gate(cirq.Rx(np.pi/7))\n",
        "# Molmer-Sorensen gate by Pi/4 \n",
        "ion_device.validate_gate(cirq.MS(np.pi/4))"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "nc4zLydMsrkV",
        "colab_type": "text"
      },
      "source": [
        "A Toffoli is an example of a gates in Cirq that the IonDevice does not support."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "ChT4QK7TsabR",
        "colab_type": "code",
        "outputId": "884ba1fd-e01c-4350-c984-c871e2a62e63",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 164
        }
      },
      "source": [
        "#Controlled gate with non-integer exponent (rotation angle must be a multiple of pi)\n",
        "ion_device.validate_gate(cirq.TOFFOLI)"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "error",
          "ename": "AttributeError",
          "evalue": "ignored",
          "traceback": [
            "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
            "\u001b[0;31mAttributeError\u001b[0m                            Traceback (most recent call last)",
            "\u001b[0;32m<ipython-input-3-940de3110cc1>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mion_device\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mvalidate_gate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcirq\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mToffoli\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
            "\u001b[0;31mAttributeError\u001b[0m: module 'cirq' has no attribute 'Toffoli'"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "1byvHcWvHx-D",
        "colab_type": "text"
      },
      "source": [
        "###Bernstein-Vazirani Algorithm\n",
        "As an example of implementing an algorithm on the IonDevice.  We examine the Bernstein-Vazirani Algorithm (BV). \n",
        "\n",
        "**Problem** Given a hidden string of $k$ bits $s$ and an oracle that outputs a single bit $y=x\\cdot s$ mod 2, find *s*.  For input string $x$ and output bit $b$, $Oracle([x,b])=[x,b\\oplus y]$\n",
        "\n",
        "**Classical Solution** We can determine $s$ bit by bit by sending bit strings with a single 1 ( $x_l = x_{{0l\n",
        "}}x_{{1l}}x_{{2l}}..x_{{kl}}$ where $x_{{jl}}=\\delta_{{jl}}$). Then each $y$ yields one bit of $s$ and after $k$ queries we have $s$.\n",
        "\n",
        "**Quantum Solution** BV uses phase kick-back to reveal the value of the $s$ in a single oracle call.  The input string starts in $|0\\rangle$ and then Hadamards are applied to yield $\\sum_x \\frac{1}{2^{{k/2}}} |x\\rangle$. The output bit starts in $|1\\rangle$ and then a Hadamard is applied yielding $|-\\rangle =\\frac{1}{\\sqrt{2}}(|0\\rangle-|1\\rangle)$.  When the Oracle is applied, all strings $x$ where $x\\cdot s =0$ mod 2 do not receive a phase.  All strings where $x\\cdot s =1$ mod 2  receive a phase of -1.  After the oracle, our state on the input register is  $\\sum_x \\frac{1}{2^{{k/2}}} (-1)^{{x.s}} |x\\rangle$.  When we apply Hadamards to the input register, this yields  $|s\\rangle$.  BV allows us to find $s$ in a single oracle call.\n",
        "\n",
        "### Ion Trap Implementation\n",
        "Oracles are note a native device gate, so we need to construct it.  A simple oracle can be constructed  by applying  CNOT gates from the input register to the output bit where there is a CNOT from bit $l$ in the input register to the output bit if $s_l=1$.  CNOT gates are also not native ion trap gates.  Below we show how to implement this sequence in Cirq using the decomposition tool to translate from CNOTSs and Hadamards to ion trap gates.\n",
        "\n",
        "\n",
        "\n",
        "\n",
        "\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "mWCh6lMVHuHT",
        "colab_type": "text"
      },
      "source": [
        "First we define the hidden string $s$ ."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "2-JF9nfaIDul",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "### length of your hidden string\n",
        "string_length = qubit_num-1\n",
        "### generate all possible strings of length string_length, and randomly choose one as your hidden string\n",
        "all_strings = [\"\".join(seq) for seq in itertools.product(\"01\", repeat=string_length)]\n",
        "hidden_string = random.choice(all_strings)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "0G36UOx5IiAt",
        "colab_type": "text"
      },
      "source": [
        "Then we construct the generic circuit."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "Ivz41tqnImIJ",
        "colab_type": "code",
        "outputId": "bb5a6623-9dec-47a9-b73f-4d001fbde2d5",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 289
        }
      },
      "source": [
        "\n",
        "### make the circuit for BV with clifford gates\n",
        "circuit = cirq.Circuit()\n",
        "circuit.append([cirq.X(qubit_list[qubit_num-1])])\n",
        "for i in range(qubit_num):\n",
        "    circuit.append([cirq.H(qubit_list[i])])\n",
        "for i in range(qubit_num-1):\n",
        "    if hidden_string[i] == '1':\n",
        "        circuit.append([cirq.CNOT(qubit_list[i], qubit_list[qubit_num-1])])\n",
        "for i in range(qubit_num - 1):\n",
        "    circuit.append([cirq.H(qubit_list[i])])\n",
        "    circuit.append([cirq.measure(qubit_list[i])])\n",
        "\n",
        "print(\"Doing Bernstein-Vazirani algorithm with hidden string\",\n",
        "      hidden_string, \"\\n\")\n",
        "print(\"Clifford Circuit:\\n\")\n",
        "print(circuit, \"\\n\")"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Doing Bernstein-Vazirani algorithm with hidden string 1011 \n",
            "\n",
            "Clifford Circuit:\n",
            "\n",
            "              ┌──┐\n",
            "0: ───H────────@─────H───M───────────\n",
            "               │\n",
            "1: ───H───H────┼M────────────────────\n",
            "               │\n",
            "2: ───H────────┼─────@───H───M───────\n",
            "               │     │\n",
            "3: ───H────────┼─────┼───@───H───M───\n",
            "               │     │   │\n",
            "4: ───X───H────X─────X───X───────────\n",
            "              └──┘ \n",
            "\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "43Y5dphQI3Be",
        "colab_type": "text"
      },
      "source": [
        "Convert to ion trap gates using KAK decomposition and circuit identities for CNOT and H."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "wxe42roTJNZ1",
        "colab_type": "code",
        "outputId": "c0b475f1-0321-406e-ddb4-f0ba8b04970a",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 1249
        }
      },
      "source": [
        "### convert the clifford circuit into circuit with ion trap native gates\n",
        "ion_circuit = ion_device.decompose_circuit(circuit)\n",
        "print(repr(ion_circuit))\n",
        "print(\"Iontrap Circuit: \\n\", ion_circuit, \"\\n\")"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "cirq.Circuit(moments=[\n",
            "    cirq.Moment(operations=[\n",
            "        cirq.X.on(cirq.LineQubit(4)),\n",
            "        cirq.Rx(np.pi*1.0).on(cirq.LineQubit(0)),\n",
            "        cirq.Rx(np.pi*1.0).on(cirq.LineQubit(1)),\n",
            "        cirq.Rx(np.pi*1.0).on(cirq.LineQubit(2)),\n",
            "        cirq.Rx(np.pi*1.0).on(cirq.LineQubit(3)),\n",
            "    ]),\n",
            "    cirq.Moment(operations=[\n",
            "        cirq.Ry(np.pi*-0.5).on(cirq.LineQubit(0)),\n",
            "        cirq.Ry(np.pi*-0.5).on(cirq.LineQubit(1)),\n",
            "        cirq.Ry(np.pi*-0.5).on(cirq.LineQubit(2)),\n",
            "        cirq.Ry(np.pi*-0.5).on(cirq.LineQubit(3)),\n",
            "        cirq.Rx(np.pi*1.0).on(cirq.LineQubit(4)),\n",
            "    ]),\n",
            "    cirq.Moment(operations=[\n",
            "        cirq.Ry(np.pi*-0.5).on(cirq.LineQubit(4)),\n",
            "        cirq.Rx(np.pi*1.0).on(cirq.LineQubit(1)),\n",
            "        cirq.Rx(np.pi*1.0).on(cirq.LineQubit(2)),\n",
            "        cirq.Ry(np.pi*0.5).on(cirq.LineQubit(0)),\n",
            "        cirq.Ry(np.pi*0.5).on(cirq.LineQubit(3)),\n",
            "    ]),\n",
            "    cirq.Moment(operations=[\n",
            "        cirq.Ry(np.pi*-0.5).on(cirq.LineQubit(1)),\n",
            "        cirq.Ry(np.pi*-0.5).on(cirq.LineQubit(2)),\n",
            "        cirq.MS(0.5*np.pi/2).on(cirq.LineQubit(0), cirq.LineQubit(4)),\n",
            "    ]),\n",
            "    cirq.Moment(operations=[\n",
            "        cirq.Rx(np.pi*-0.5).on(cirq.LineQubit(0)),\n",
            "        cirq.Rx(np.pi*-0.5).on(cirq.LineQubit(4)),\n",
            "        cirq.MeasurementGate(1, '1', ()).on(cirq.LineQubit(1)),\n",
            "        cirq.MeasurementGate(1, '2', ()).on(cirq.LineQubit(2)),\n",
            "    ]),\n",
            "    cirq.Moment(operations=[\n",
            "        cirq.Ry(np.pi*-0.5).on(cirq.LineQubit(0)),\n",
            "        cirq.MS(0.5*np.pi/2).on(cirq.LineQubit(3), cirq.LineQubit(4)),\n",
            "    ]),\n",
            "    cirq.Moment(operations=[\n",
            "        cirq.Rx(np.pi*-0.5).on(cirq.LineQubit(3)),\n",
            "        cirq.Rx(np.pi*-0.5).on(cirq.LineQubit(4)),\n",
            "        cirq.Rx(np.pi*1.0).on(cirq.LineQubit(0)),\n",
            "    ]),\n",
            "    cirq.Moment(operations=[\n",
            "        cirq.Ry(np.pi*-0.5).on(cirq.LineQubit(3)),\n",
            "        cirq.Ry(np.pi*-0.5).on(cirq.LineQubit(0)),\n",
            "    ]),\n",
            "    cirq.Moment(operations=[\n",
            "        cirq.MeasurementGate(1, '0', ()).on(cirq.LineQubit(0)),\n",
            "        cirq.Rx(np.pi*1.0).on(cirq.LineQubit(3)),\n",
            "    ]),\n",
            "    cirq.Moment(operations=[\n",
            "        cirq.Ry(np.pi*-0.5).on(cirq.LineQubit(3)),\n",
            "    ]),\n",
            "    cirq.Moment(operations=[\n",
            "        cirq.MeasurementGate(1, '3', ()).on(cirq.LineQubit(3)),\n",
            "    ]),\n",
            "])\n",
            "Iontrap Circuit: \n",
            "                                       ┌──────────────────┐\n",
            "0: ───Rx(π)───Ry(-0.5π)───Ry(0.5π)──────────────MS(0.25π)────Rx(-0.5π)───Ry(-0.5π)───Rx(π)───────Ry(-0.5π)───M───────────────────────\n",
            "                                                │\n",
            "1: ───Rx(π)───Ry(-0.5π)───Rx(π)────────Ry(-0.5π)┼────────────M───────────────────────────────────────────────────────────────────────\n",
            "                                                │\n",
            "2: ───Rx(π)───Ry(-0.5π)───Rx(π)────────Ry(-0.5π)┼────────────M───────────────────────────────────────────────────────────────────────\n",
            "                                                │\n",
            "3: ───Rx(π)───Ry(-0.5π)───Ry(0.5π)──────────────┼────────────────────────MS(0.25π)───Rx(-0.5π)───Ry(-0.5π)───Rx(π)───Ry(-0.5π)───M───\n",
            "                                                │                        │\n",
            "4: ───X───────Rx(π)───────Ry(-0.5π)─────────────MS(0.25π)────Rx(-0.5π)───MS(0.25π)───Rx(-0.5π)───────────────────────────────────────\n",
            "                                      └──────────────────┘ \n",
            "\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "6Znix0ZLI_FP",
        "colab_type": "text"
      },
      "source": [
        "We can use cirq.merge_single_qubit_gates_into_phased_x_z(circuit)"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "rt-MfhxXJAK7",
        "colab_type": "code",
        "outputId": "d8b8f67c-2938-474c-a798-d67fff1c8dbe",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 210
        }
      },
      "source": [
        "### convert the clifford circuit into circuit with ion trap native gates\n",
        "ion_circuit = ion_device.decompose_circuit(circuit)\n",
        "optimized_ion_circuit=cirq.merge_single_qubit_gates_into_phased_x_z(ion_circuit)\n",
        "print(\"Iontrap Circuit: \\n\", ion_circuit, \"\\n\")"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Iontrap Circuit: \n",
            " 0: ───X────────────────MS(0.25π)───X^0.5─────────────────────────────M───────────\n",
            "                       │\n",
            "1: ────────────────────┼───────────M─────────────────────────────────────────────\n",
            "                       │\n",
            "2: ────────────────────┼───────────M─────────────────────────────────────────────\n",
            "                       │\n",
            "3: ───X────────────────┼────────────────────MS(0.25π)───X^0.5────────────────M───\n",
            "                       │                    │\n",
            "4: ───Y^-0.5───────────MS(0.25π)───X^-0.5───MS(0.25π)───X^-0.5─────────────────── \n",
            "\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "_OI0PKG2JrfG",
        "colab_type": "text"
      },
      "source": [
        "We can compare then simulate both circuits"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "kCsfQim5KARZ",
        "colab_type": "code",
        "outputId": "b0cc373a-0877-4034-b72d-1678915d8d7c",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 70
        }
      },
      "source": [
        "### run the ion trap circuit\n",
        "simulator = Simulator()\n",
        "clifford_result = simulator.run(circuit)\n",
        "result = simulator.run(ion_circuit)\n",
        "\n",
        "measurement_results = ''\n",
        "for i in range(qubit_num-1):\n",
        "    if result.measurements[str(i)][0][0]:\n",
        "        measurement_results += '1'\n",
        "    else:\n",
        "        measurement_results += '0'\n",
        "\n",
        "print(\"Hidden string is:\", hidden_string)\n",
        "print(\"Measurement results are:\", measurement_results)\n",
        "print(\"Found answer using Bernstein-Vazirani:\", hidden_string == measurement_results)\n"
      ],
      "execution_count": 0,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Hidden string is: 1001\n",
            "Measurement results are: 1001\n",
            "Found answer using Bernstein-Vazirani: True\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "Q1OStHBa0Aur",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        ""
      ],
      "execution_count": 0,
      "outputs": []
    }
  ]
}